package com.lisp.springframework.tx.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.google.common.collect.ImmutableMap;
import com.lisp.springframework.tx.model.Foo;

@Repository
public class NamedJdbcTemplateDaoImpl implements NamedJdbcTemplateDao {
    
    private static final FooMapper FOO_MAPPER = new FooMapper();

    private NamedParameterJdbcTemplate namedParamJdbcTemplate;
    
    public NamedJdbcTemplateDaoImpl(DataSource ds) {
        this.namedParamJdbcTemplate = new NamedParameterJdbcTemplate(ds);
    }
    
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Foo find(long id) {
        return namedParamJdbcTemplate.queryForObject(
                "select * from foo where id=:id", ImmutableMap.of("id", id), FOO_MAPPER);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void insert(Foo foo) {
        namedParamJdbcTemplate.update(
                "insert into foo(id, work_id, update_date) values (:id, :workId, :updateDate)",
                new BeanPropertySqlParameterSource(foo));
    }
    
    @Override
    public List<Foo> findByIdIn(List<Long> ids) {
        return namedParamJdbcTemplate.query(
                "select * from foo where id in (:ids)", ImmutableMap.of("ids", ids), FOO_MAPPER);
    }

    private static final class FooMapper implements RowMapper<Foo> {
        
        @Override
        public Foo mapRow(ResultSet rs, int rowNum) throws SQLException {
            Foo ret = new Foo();
            ret.setId(rs.getLong("id"));
            ret.setWorkId(rs.getInt("work_id"));
            ret.setUpdateDate(rs.getDate("update_date"));
            return ret;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void update(Foo foo) {
        namedParamJdbcTemplate.update("update foo set work_id=:workId, update_date=:updateDate where id=:id", 
                new BeanPropertySqlParameterSource(foo));
    }
}
